package com.darren.befriend.fragments;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.json.JSONException;
import org.json.JSONObject;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.darren.befriend.HomeActivity;
import com.darren.befriend.R;
import com.darren.befriend.adapters.ChatItemAdapter;
import com.darren.befriend.models.BubbleData;
import com.darren.befriend.utilities.LogUtil;
import com.darren.befriend.utilities.Utilities;
import com.darren.befriend.views.PullToRefreshListView;
import com.darren.befriend.views.PullToRefreshListView.OnRefreshListener;
import com.parse.CountCallback;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.ParsePush;
import com.parse.ParseQuery;
import com.parse.ParseQuery.CachePolicy;
import com.parse.ParseUser;
import com.parse.SaveCallback;

public class ChatFragment extends Fragment implements View.OnClickListener,
		OnRefreshListener {
	private static ParseUser mUser;
	private int MAX_ENTRIES_LOADED = 30;
	private boolean isLoading;
	private int mMessageCount;
	private int skip, skipMore;
	private int indexPoint = -1;
	private boolean isEmpty;
	private boolean isMore;
	private ParseUser mCurrentUser;
	private ArrayList<BubbleData> bubbleData;
	private EditText mChatMessage;
	private PullToRefreshListView mChatList;
	private ChatItemAdapter adapter;
	private CountDownTimer loadMoreTimer;
	private LinearLayout mInfoLayout;
	private boolean mIsSent;

	public static ChatFragment makeInstance(ParseUser user) {

		ChatFragment fragment = new ChatFragment();
		mUser = user;
		return fragment;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		ViewGroup view = (ViewGroup) inflater.inflate(
				R.layout.layout_chat_fragment, container, false);
		mChatMessage = (EditText) view.findViewById(R.id.chat_input);
		mChatList = (PullToRefreshListView) view.findViewById(R.id.chat_list);
		mInfoLayout = (LinearLayout) view.findViewById(R.id.chat_infor_layout);
		ImageView chatSendBtn = (ImageView) view.findViewById(R.id.chat_send);
		ImageView reportBtn = (ImageView) view
				.findViewById(R.id.chat_infor_report);
		ImageView viewProfileBtn = (ImageView) view
				.findViewById(R.id.chat_infor_view_profile);
		ImageView blockBtn = (ImageView) view
				.findViewById(R.id.chat_infor_block);
		blockBtn.setOnClickListener(this);
		reportBtn.setOnClickListener(this);
		viewProfileBtn.setOnClickListener(this);
		chatSendBtn.setOnClickListener(this);
		mChatList.setOnRefreshListener(this);
		FriendsFragment.needToReloadList = false;
		return view;
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);
		if (getActivity() instanceof HomeActivity) {
			if (mUser != null) {

				new FetchInfoAsynTask().execute();
				String fullName = mUser.get("fullName").toString();
				if (fullName.contains("_local")) {

					fullName = fullName.replace("_local", "");
				}

				((HomeActivity) getActivity()).setActivityTitle(fullName);
			}

			((HomeActivity) getActivity()).showRightButtonImg(true);
			((HomeActivity) getActivity()).setRightImage(R.drawable.icon_info);
			((HomeActivity) getActivity()).setLeftImage(R.drawable.item_back);
			mCurrentUser = ((HomeActivity) getActivity()).getCurrentUser();
			if (bubbleData == null) {

				bubbleData = new ArrayList<BubbleData>();
			} else {

				mIsSent = true;
				adapter = null;
				reloadChatList();
			}

			mIsSent = true;
			loadLocalChat();
		}
	}

	@Override
	public void onClick(View v) {
		int id = v.getId();
		switch (id) {
		case R.id.chat_send:

			if (!mChatMessage.getText().toString().trim().equals("")) {

				sendChat();
			}

			break;

		case R.id.header_right_btn:

			loadMoreChat();
			break;
		case R.id.chat_infor_block:

			blockUser(mUser);
			break;
		case R.id.chat_infor_view_profile:

			UserInfoDetailFragment fragment = UserInfoDetailFragment
					.makeInstance(mUser, true, false, null);
			HomeActivity activity = (HomeActivity) getActivity();
			activity.switchContentWithNormalAnimation(fragment);
			pauseTimer();
			break;
		case R.id.chat_infor_report:

			Utilities.showAlertMessage(getActivity(),
					getString(R.string.report_message), "");
			break;
		default:
			break;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.support.v4.app.Fragment#onResume()
	 */
	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.support.v4.app.Fragment#onPause()
	 */
	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();

		Utilities.hideKeyboard(getActivity());
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.support.v4.app.Fragment#onDestroy()
	 */
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		mUser = null;
		pauseTimer();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.darren.befriend.views.PullToRefreshListView.OnRefreshListener#onRefresh
	 * ()
	 */
	@Override
	public void onRefresh() {
		// TODO Auto-generated method stub

		loadMoreChat();
		mChatList.onRefreshComplete();
	}

	/**
	 * Show information layout when click to right button
	 * */
	public void showInfoLayout() {

		if (mInfoLayout.getVisibility() == View.VISIBLE) {

			mInfoLayout.setVisibility(View.GONE);
		} else {

			mInfoLayout.setVisibility(View.VISIBLE);
		}
	}

	/**
	 * Load local chat
	 * */
	private void loadLocalChat() {

		if (isLoading) {

			return;
		}

		isLoading = true;
		ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("ChatRoom");
		query.addDescendingOrder("createdAt");
		query.countInBackground(new CountCallback() {

			@Override
			public void done(int number, ParseException arg1) {
				if (arg1 == null) {

					mMessageCount = number;
					skip = 0;
					loadQuery();
				} else {

					isLoading = false;
				}
			}
		});
	}

	private void loadMoreChat() {

		isMore = true;
		ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("ChatRoom");
		query.addDescendingOrder("createdAt");
		if (indexPoint == 0) {

			return;
		}

		query.countInBackground(new CountCallback() {

			@Override
			public void done(int number, ParseException error) {
				if (error == null) {

					mMessageCount = number;
					skipMore = mMessageCount - indexPoint;
					loadMoreQuery();
				} else {

					isMore = false;
					if (loadMoreTimer == null) {

						startTimer();
					}
				}
			}
		});
	}

	private void loadMoreQuery() {

		ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("ChatRoom");
		query.addDescendingOrder("createdAt");
		query.setCachePolicy(CachePolicy.CACHE_THEN_NETWORK);
		query.setLimit(MAX_ENTRIES_LOADED);
		query.setSkip(skipMore);
		query.findInBackground(new FindCallback<ParseObject>() {

			@Override
			public void done(List<ParseObject> objects, ParseException error) {
				if (error == null) {

					if (objects.size() == 0 || !isMore) {

						reloadChatList();
						if (loadMoreTimer == null) {

							startTimer();
						}

						isMore = false;
						return;
					}

					skipMore += objects.size();
					String myName = mCurrentUser.getUsername();
					int addedCount = 0;
					for (int i = 0; i < objects.size(); i++) {

						ParseObject message = objects.get(i);
						if (!(message.get("sender").equals(myName) && message
								.get("receiver").equals(mUser.getUsername()))
								&& !(message.get("receiver").equals(myName) && message
										.get("sender").equals(
												mUser.getUsername()))) {
							continue;
						}

						addedCount++;

						if (message.get("sender").equals(myName)) {
							Date date = message.getCreatedAt();
							BubbleData msgBubble = new BubbleData(date, String
									.valueOf(message.get("text")), 0);
							msgBubble.objectId = message.getObjectId();
							msgBubble.avatar = getUserImage(mCurrentUser);
							if (msgBubble.avatar.equals("")) {

								Bitmap photoBitmap = getPhotoBitmap((byte[]) mCurrentUser
										.get("Photo"));
								msgBubble.setPhoto(photoBitmap);
							}

							bubbleData.add(0, msgBubble);
						} else {
							Date date = message.getCreatedAt();
							BubbleData msgBubble = new BubbleData(date, String
									.valueOf(message.get("text")), 1);
							msgBubble.objectId = message.getObjectId();
							msgBubble.avatar = getUserImage(mUser);
							if (msgBubble.avatar.equals("")) {

								Bitmap photoBitmap = getPhotoBitmap((byte[]) mUser
										.get("Photo"));
								msgBubble.setPhoto(photoBitmap);
							}

							bubbleData.add(0, msgBubble);
						}
					}

					if (addedCount == 0) {

						loadMoreQuery();
					} else {

						indexPoint = mMessageCount - skipMore;
						reloadChatList();
						isMore = false;
						if (loadMoreTimer == null) {

							startTimer();
						}
					}
				}
			}
		});
	}

	/**
	 * Query messages
	 * */
	private void loadQuery() {

		ParseQuery<ParseObject> query = new ParseQuery<ParseObject>("ChatRoom");
		query.addDescendingOrder("createdAt");
		query.setCachePolicy(CachePolicy.CACHE_THEN_NETWORK);
		query.setLimit(MAX_ENTRIES_LOADED);
		query.setSkip(skip);
		query.findInBackground(new FindCallback<ParseObject>() {

			@Override
			public void done(List<ParseObject> objects, ParseException error) {
				if (error == null && mUser != null) {

					if (objects.size() == 0) {

						// boolean isEnd = false;
						reloadChatList();
						isEmpty = true;
						isLoading = false;
						return;
					}

					for (BubbleData bb : bubbleData) {
						// BubbleData bb = bubbleData.get(bubbleData.size() -
						// 1);
						if (bb.type == 2) {

							bubbleData.remove(bb);
						}
					}

					skip += objects.size();
					String myName = mCurrentUser.getUsername();
					int start = objects.size();
					BubbleData lastBubble = null;
					if (bubbleData != null && bubbleData.size() > 0) {

						lastBubble = bubbleData.get(bubbleData.size() - 1);
					}

					if (lastBubble != null) {

						for (start = 0; start < objects.size(); start++) {

							ParseObject message = objects.get(start);
							if (message.getObjectId().equalsIgnoreCase(
									lastBubble.objectId)) {

								break;
							}
						}
					}

					for (int i = start - 1; i >= 0; i--) {
						ParseObject message = objects.get(i);
						if (!(message.get("sender").equals(myName) && message
								.get("receiver").equals(mUser.getUsername()))
								&& !(message.get("receiver").equals(myName) && message
										.get("sender").equals(
												mUser.getUsername()))) {
							continue;
						}

						try {

							if (message.get("sender").equals(myName)) {

								Date date = message.getCreatedAt();
								BubbleData msgBubble = new BubbleData(date,
										String.valueOf(message.get("text")), 0);
								msgBubble.objectId = message.getObjectId();
								msgBubble.avatar = getUserImage(mCurrentUser);
								if (msgBubble.avatar.equals("")) {

									Bitmap photoBitmap = getPhotoBitmap((byte[]) mCurrentUser
											.get("Photo"));
									msgBubble.setPhoto(photoBitmap);
								}

								bubbleData.add(msgBubble);
								mIsSent = true;
							} else {

								Date date = message.getCreatedAt();
								BubbleData msgBubble = new BubbleData(date,
										String.valueOf(message.get("text")), 1);
								msgBubble.objectId = message.getObjectId();
								msgBubble.avatar = getUserImage(mUser);
								if (msgBubble.avatar.equals("")) {

									Bitmap photoBitmap = getPhotoBitmap((byte[]) mUser
											.get("Photo"));
									msgBubble.setPhoto(photoBitmap);
								}

								bubbleData.add(msgBubble);
								mIsSent = true;
							}
						} catch (Exception ex) {

						}
					}

					if (bubbleData.size() == 0 && isEmpty == false) {

						loadQuery();
					} else {

						if (bubbleData.size() != 0) {

							isEmpty = false;
							if (indexPoint == -1) {

								indexPoint = mMessageCount - skip;
							}

							if (start != 0) {

								reloadChatList();
								if (loadMoreTimer == null) {

									startTimer();
								}
								// mChatList.setAdapter(adapter);
							}
						}

						isLoading = false;
					}
				} else {

					indexPoint = mMessageCount - skipMore;
					isLoading = false;
				}
			}
		});
	}

	private void sendChat() {

		BubbleData senddingBubble = new BubbleData(new Date(
				System.currentTimeMillis()), "", 2);
		bubbleData.add(senddingBubble);
		mIsSent = true;
		reloadChatList();
		if (mChatMessage.getText().length() <= 0) {

			return;
		}

		ParseObject newMessage = ParseObject.create("ChatRoom");
		newMessage.put("text", mChatMessage.getText().toString());
		newMessage.put("receiver", mUser.getUsername());
		newMessage.put("sender", mCurrentUser.getUsername());
		newMessage.put("date", new Date());
		newMessage.saveInBackground(new SaveCallback() {

			@Override
			public void done(ParseException arg0) {
				// TODO: type
				mIsSent = true;
				loadLocalChat();
			}
		});

		if (!(Boolean) mUser.get("Status")) {

			String fullName = mCurrentUser.get("fullName").toString()
					.replace("_local", "");
			String message = String.format(getString(R.string.send_title),
					fullName);
			ParsePush push = new ParsePush();
			push.setChannel("CH_" + mUser.getUsername());
			JSONObject data = null;
			try {

				data = new JSONObject("{\"alert\": \" " + message
						+ "\",\"badge\": \"Increment\"}");
			} catch (JSONException e) {

				e.printStackTrace();
			}

			push.setData(data);
			push.setExpirationTimeInterval(86400);
			push.sendInBackground();
		}

		mChatMessage.setText("");
	}

	private void reloadChatList() {

		try {
			if (adapter == null) {

				adapter = new ChatItemAdapter(getActivity(), bubbleData);
				mChatList.setAdapter(adapter);
			} else {

				adapter.notifyDataSetChanged();
			}

			if (mIsSent) {

				mChatList.postDelayed(new Runnable() {
					@Override
					public void run() {

						mChatList.setSelection(adapter.getCount() - 1);
					}
				}, 200);

				mIsSent = false;
			}
		} catch (Exception ex) {

			LogUtil.e("reloadChatList", "Error");
		}
	}

	/**
	 * Start timer to load message every 3 seconds
	 * */
	private void startTimer() {

		loadMoreTimer = new CountDownTimer(Long.MAX_VALUE, 3000) {

			@Override
			public void onTick(long millisUntilFinished) {
				// TODO Auto-generated method stub

				loadLocalChat();
			}

			@Override
			public void onFinish() {
				// TODO Auto-generated method stub

			}
		};

		loadMoreTimer.start();
	}

	private void pauseTimer() {

		if (loadMoreTimer != null) {

			loadMoreTimer.cancel();
			loadMoreTimer = null;
		}
	}

	/**
	 * Block user
	 * */
	@SuppressWarnings("unchecked")
	private void blockUser(ParseUser blockUser) {

		ArrayList<String> friendList = (ArrayList<String>) mCurrentUser
				.get("Friends");
		if (friendList != null) {

			for (String user : friendList) {

				if (user.equals(blockUser.getUsername())) {

					friendList.remove(user);
					break;
				}
			}
		}

		mCurrentUser.put("Friends", friendList);
		ArrayList<String> enemy = (ArrayList<String>) mCurrentUser.get("Enemy");
		boolean isFound = false;
		if (enemy != null) {

			for (String user : enemy) {

				user = user.replace("$$$", ":");
				String userName = user.split(":")[0];
				if (userName.equals(blockUser.getUsername())) {

					isFound = true;
					break;
				}
			}
		}

		if (!isFound) {

			String blockId = String.format("%s$$$%d", blockUser.getUsername(),
					System.currentTimeMillis());
			enemy.add(blockId);
		}

		mCurrentUser.put("Enemy", enemy);
		mCurrentUser.saveInBackground();
		Utilities.showAlertMessage(getActivity(),
				getString(R.string.block_message), "");
	}

	private class FetchInfoAsynTask extends AsyncTask<Void, Void, Void> {

		/*
		 * (non-Javadoc)
		 * 
		 * @see android.os.AsyncTask#doInBackground(java.lang.Object[])
		 */
		@Override
		protected Void doInBackground(Void... params) {
			// TODO Auto-generated method stub

			try {

				mUser.getParseObject("MeInfo").fetchIfNeeded();
			} catch (Exception e) {
				// TODO Auto-generated catch block
			}

			return null;
		}

	}

	private String getUserImage(ParseUser user) {

		String url = "";
		if (user != null) {

			String fullName = "";
			try {

				fullName = user.get("fullName").toString();
			} catch (Exception ex) {

			}

			if (fullName != null) {

				if (!fullName.contains("_local")) {

					url = String.format(
							getResources().getString(R.string.profile_url),
							user.getUsername());

				} else {

					url = "";
				}
			}
		}

		return url;
	}

	private Bitmap getPhotoBitmap(byte[] bytes) {

		try {

			Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0,
					bytes.length);
			return bitmap;
		} catch (Exception ex) {

			return null;
		}
	}
}
